package com.hexun.dubbo.overview;

import com.alibaba.dubbo.rpc.protocol.rest.support.ContentType;
import org.jboss.resteasy.core.Dispatcher;
import org.jboss.resteasy.core.ResourceMethodInvoker;
import org.jboss.resteasy.core.ResourceMethodRegistry;
import org.springframework.stereotype.Service;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

@Service
@Path("overview")
@Consumes({MediaType.APPLICATION_JSON, MediaType.TEXT_XML})
@Produces({ContentType.APPLICATION_JSON_UTF_8, ContentType.TEXT_XML_UTF_8})
public class ResteasyOverview implements IResteasyOverview {
    List<ResourceDescription> getAvailableEndpoints(@Context Dispatcher dispatcher) {
        ResourceMethodRegistry registry = (ResourceMethodRegistry) dispatcher.getRegistry();
        return ResourceDescription.fromBoundResourceInvokers(registry.getBounded().entrySet());
    }

    @Override
    @GET
    @Produces(MediaType.TEXT_HTML)
    public Response getAvailableEndpointsHtml(@Context Dispatcher dispatcher) {
        StringBuilder sb = new StringBuilder();
        List<ResourceDescription> descriptions = getAvailableEndpoints(dispatcher);
        sb.append("<!DOCTYPE html><html>\n");
        sb.append("<head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />" +
                "<script src=\"https://cdn.bootcss.com/jquery/1.10.1/jquery.min.js\"></script>" +
                "</head><body>");
        sb.append("<h1 style='border:solid 1px;'>").append("REST interface 健康检查").append("</h1>");
        sb.append("<li>").append("COOKIE  ").append("<input type='text' id='cookie' name='cookie' style='width:100%;height:100px' />").append("</li>");
        for (ResourceDescription resource : descriptions) {
            sb.append("<h2 style='border:solid 1px;'>父路径-->").append(resource.basePath).append("</h2>");
            sb.append("<ul style='border:solid 1px;'>");

            for (MethodDescription methodDescription : resource.calls) {
                ResourceMethodInvoker resourceInvoker = (ResourceMethodInvoker) methodDescription.resourceInvoker;
                sb.append("<li style='color: blue'>").append("方法说明>>").append(methodDescription.apiMonitor == null ? "" : methodDescription.apiMonitor.value()).append("</li>");
                sb.append("<li>").append("方法>>").append(methodDescription.method).append("</li>");
                sb.append("<li>").append("HttpMethod>>").append(getHttpMethod(resourceInvoker.getHttpMethods())).append("</li>");
                sb.append("<li>").append("resteasy--路径>>").append("</li>");
                sb.append("<strong style='color:red'>").append(methodDescription.path).append("</strong>");
                if (methodDescription.apiMonitor != null) {
                    sb.append("<li class='data'>").append(methodDescription.apiMonitor.monitorData()).append("</strong>");
                }
                sb.append("<ul>");
                if (resourceInvoker.getConsumes() != null) {
                    sb.append("<li>").append("Consumes: ").append(mostPreferredOrNull(resourceInvoker.getConsumes())).append("</li>");
                }
                if (resourceInvoker.getProduces() != null) {
                    sb.append("<li>").append("Produces: ").append(mostPreferredOrNull(resourceInvoker.getProduces())).append("</li>");
                }
                sb.append("</ul>");
                sb.append("<br/><br/><br/>");
            }
            sb.append("</ul>");
        }
        sb.append("</body></html>");

        return Response.ok(sb.toString()).build();
    }

    /**
     * print media type
     *
     * @param mediaTypes
     * @return
     */
    private static String mostPreferredOrNull(MediaType[] mediaTypes) {
        if (mediaTypes == null || mediaTypes.length < 1) {
            return null;
        } else {
            StringBuilder builder = new StringBuilder();
            for (MediaType mediaType : mediaTypes) {
                builder.append(mediaType.toString()).append(" | ");
            }
            builder.delete(builder.length() - 2, builder.length() - 1);
            return builder.toString();
        }
    }

    /**
     * 聚合 http method
     *
     * @param httpMethods
     * @return
     */
    private static String getHttpMethod(Set<String> httpMethods) {
        StringBuilder builder = new StringBuilder();
        Iterator<String> iterator = httpMethods.iterator();
        while (iterator.hasNext()) {
            builder.append(iterator.next() + ",");
        }
        builder.delete(builder.length() - 1, builder.length());
        return builder.toString();
    }
}
